package com.saascloud.auth.core;

import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.MimeHeaders;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.lang.reflect.Field;

/**
 * 放行网关加的令牌
 */
@Slf4j
public class RemoveBearerHeaderFilter implements Filter {
    @Autowired
    MyAuthorityPermit permit;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String apiPath = httpRequest.getMethod() + httpRequest.getServletPath();
        if (!MyAuthorityPermit.OPTIONS.equalsIgnoreCase(httpRequest.getMethod()) //过滤跨域请求
                &&!apiPath.contains(MyAuthorityPermit.SUPER_API)
                &&!permit.checkInterfaceRealeased(apiPath) //判断需要令牌  不去掉网关的Bearer令牌（接口不放行）
                &&(permit.release(httpRequest.getServletPath())||permit.release(apiPath))) { //判断不需要令牌  去掉网关的Bearer令牌 （接口放行）
            // 本地放行的接口在网关加了OAuth又被加上了token，这个位置判断如果已经放行的及时加了令牌都需要去掉
            // 否则本地会校验这个网关的令牌报错
            log.info("网关放行地址---{}--RemoveBearerHeaderFilter.doFilter",apiPath);
            removeBearerHeader(httpRequest);
        }
        filterChain.doFilter(httpRequest, response);

    }

    /**
     * 移除令牌
     * @param request
     */
    private void removeBearerHeader(HttpServletRequest request){
        Class<? extends HttpServletRequest> requestClass = request.getClass();
        try {
            Field request1 = requestClass.getDeclaredField("request");
            request1.setAccessible(true);
            Object o = request1.get(request);
            Field coyoteRequest = o.getClass().getDeclaredField("coyoteRequest");
            coyoteRequest.setAccessible(true);
            Object o1 = coyoteRequest.get(o);
            Field headers = o1.getClass().getDeclaredField("headers");
            headers.setAccessible(true);
            MimeHeaders o2 = (MimeHeaders)headers.get(o1);
            // 移除网关令牌
            o2.removeHeader("authorization");
        } catch (Exception e) {
            log.error("取消网关令牌失败",e);
        }
    }


}
